package org.xml.xpath4js.client;

/* 
xpath4js is a GWT implementation of XPath 2.0 
Copyright (C) 2010  Peter Schonefeld (peter dot schonefeld at gmail)

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

import java.util.Iterator;
import java.util.Vector;

public class XPathNode extends XPathItem{

	Integer			_documentOrder = 0;
	XPathNode		_ownerDocument;
	String			_xmlBase = "";
	String			_qName = "";
	XPathNodeType	_nodeType = XPathNodeType.ELEMENT_NODE;
	XPathNode		_parent;
	String			_namespace = "";

	/**
     * @gwt.typeArgs <com.artbase.xpath.client.XPathNode>
     */		
	Vector _attributes = new Vector();

	/**
     * @gwt.typeArgs <com.artbase.xpath.client.XPathNode>
     */		
	Vector _children = new Vector();

	XPathSequence _typedValue = new XPathSequence();
		
	public XPathNode(){
		stringValue = "";
		xsdType = "xs:anySimpleType";
	};	
	
	public XPathNode(String sVal,
			   String sXSDType,
			   Integer docOrder,
			   XPathNode ownerDoc,
			   String xmlBase,
			   XPathNodeType nodeType,
			   String qName,
			   XPathNode parent){
		this.stringValue = sVal;
		this.xsdType = sXSDType;
		this._documentOrder = docOrder;
		this._ownerDocument = ownerDoc;
		this._xmlBase = xmlBase;
		this._qName = qName;
		this._nodeType = nodeType;
		this._parent = parent;	
	};
	
	public boolean IsNode(){ return true; }
	
	//used for identity comparison of nodes.	
	public boolean Is(XPathItem item){
		boolean result = false;
		if(item.IsNode()){ 
			XPathNode node = (XPathNode) item;
			String s1 = this._ownerDocument.toString();
			String s2 = node.GetOwnerDocument().toString();
			if( (s1.compareTo(s2) == 0) && 
				(this._documentOrder==node.GetDocumentOrder()) )
				result = true;
		}
		return result;		
	}

	//Each node has a specified type as it relates to the XPath Data
	//Model. See enum XPathNodeType in header file.	
	public XPathNodeType GetNodeType(){
		return _nodeType;
	};
	
	public Integer GetDocumentOrder() {
		return _documentOrder;			
	};
	
	public XPathNode GetOwnerDocument(){
		return this._ownerDocument;		
	};

	public void SetOwnerDocument(XPathNode n){
		this._ownerDocument = n;
	}
	
	public String GetQName(){
		return _qName;		
	}; 		
	
	public String GetLocalName(){
		int separateAt = _qName.indexOf(':');
		if(separateAt>-1) 
			return _qName.substring(separateAt+1);
		else
	        return _qName;
	};		
	
	// returns Expanded-QName	(ns URI:LocalName)	
	// the Expanded-QName is (Namespace URI":")?LocalName of a node
	// TODO: must implement namespaces	
	public String GetExpandedQName(){
		return _qName;		
	};	
   
	// return child XPathNode instance at index, i	
	public XPathNode GetChildAt(int i){
		return (XPathNode) _children.get(i);		
	}; 
	
	//return all child nodes in a sequence
	public XPathSequence GetChildren(){
		XPathSequence result = new XPathSequence();
		result.GetItems().addAll(0,this._children);
		return result;		
	};
	
	//return the child nodes of all descendant items in a sequence	
	public XPathSequence GetDescendants(){
		XPathSequence result = new XPathSequence();
		/**
	     * @gwt.typeArgs <com.artbase.xpath.client.XPathNode>
	     */			
		Iterator it = this._children.iterator();
		while(it.hasNext()){
			XPathNode i = (XPathNode) it.next();
			result.GetItems().add(i);
			result.ConcatSequence(i.GetDescendants());
		}
		return result;		
	};

	//return attribute (XPathTerm instance) at index, i
	//will return XPathNode instance of _nodeType = ATTRIBUTE_NODE
	public XPathNode GetAttributeAt(int i){
		return (XPathNode) _attributes.get(i);		
	};
	 
	//will return the parent node of an attribute or
	//child node. Will return null if the document node. 	
	public XPathNode GetParent(){
		return (XPathNode) _parent; //GWT Compile
	}; 

	//Will insert an instance of XPathNode in the 
	//_children member at position i of the collection	
	public void AppendChild(XPathNode child){
		_children.add(child);
	};
	
	public void AppendAttribute(XPathNode attr){
		_attributes.add(attr);
	}

	//Mutators
	// set child XPathTerm instance at index, i	
	public void SetChildAt(int i, XPathNode node){
		_children.add(i,node);			
	};
	
	// set attribute (CXPathTerm instance) at i	
	public void SetAttributeAt(int i, XPathNode attr){
		_attributes.add(i, attr);
	}; 

	public void setNSNode(){
		//TODO: Not Implemented
	};
	
	//public void setStringValue(String sVal){};
	//public void ResetChildren(){};
	//public void ResetAttributes(){};
	public boolean HasChildNodes(){
		return _children.size() > 0;
	};
	
	public boolean HasAttributes(){
		return _attributes.size() > 0;
	};

	public String toString(){
		String s = "";
		switch(this._nodeType){
			case ELEMENT_NODE:
				s = this.GetQName();
				break;
			case ATTRIBUTE_NODE:
				s = "@"+this.GetQName();
				break;
			case DOCUMENT_NODE:
				s = this.GetQName();
				break;
			case TEXT_NODE:
				s = "\""+this.stringValue+"\"";
				break;
		}
		return s;		
	};	
	
}
